﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using Library.Util;
namespace Library.Winform.Draw {
  public class ArrowDraw : LineDraw {
    private int _arrowLen;
    private double _arrowAngle;
    private Color _arrowColor;
    public override void ReadFrom(System.IO.Stream stream) {
      stream.Read(out _arrowLen);
      stream.Read(out _arrowAngle);
      _arrowColor = ReadColorFromStream(stream);
      base.ReadFrom(stream);
    }

    public override void WriteTo(System.IO.Stream stream) {
      stream.Write(_arrowLen);
      stream.Write(_arrowAngle);
      WriteColorToStream(stream, _arrowColor);
      base.WriteTo(stream);
    }

    public override object Clone() {
      var arrow = new ArrowDraw();
      FillOriginalTo(arrow);
      return arrow;
    }

    protected void FillOriginalTo(ArrowDraw arrawDraw) {
      arrawDraw._arrowLen = _arrowLen;
      arrawDraw._arrowColor = _arrowColor;
      arrawDraw._arrowAngle = _arrowAngle;
      base.FillOriginalTo(arrawDraw);
    }

    public ArrowDraw() {
      Init();
    }

    public ArrowDraw(int fromX, int fromY, int toX, int toY)
      : base(fromX, fromY, toX, toY) {
      Init();
    }

    private void Init() {
      ArrowLen = 10;
      ArrowAngle = 40 * Math.PI / 180;
      ArrowColor = Color.Black;
    }

    public Color ArrowColor { get { return _arrowColor; } set { _arrowColor = value; } }
    /// <summary>
    /// Arrow length
    /// </summary>
    public int ArrowLen { get { return _arrowLen; } set { _arrowLen = value; } }
    /// <summary>
    /// radian value for corner of arraw
    /// </summary>
    public double ArrowAngle {
      get { return _arrowAngle; }
      set {
        _arrowAngle = value;
      }
    }

    protected override void DrawMe(Graphics g) {
      g.SmoothingMode = SmoothingMode.AntiAlias;
      using (var pen = new Pen(PenColor, PenWidth)) {
        var fromX = From.X - ScrollOffset.X;
        var fromY = From.Y - ScrollOffset.Y;
        var toX = To.X - ScrollOffset.X;
        var toY = To.Y - ScrollOffset.Y;
        Pen shadowPen = ShadowLen > 0 ? new Pen(ShadowColor) : null;
        DrawLine(g, pen, shadowPen, ShadowLen, fromX, fromY, toX, toY);
        if (shadowPen != null) shadowPen.Dispose();
        DrawArrow(toX, fromX, toY, fromY, g);
      }
    }

    private void DrawArrow(int tipX, int tailX, int tipY, int tailY, Graphics g) {
      int dx = tipX - tailX;
      int dy = tipY - tailY;

      double theta = Math.Atan2(dy, dx);

      //double rad =// 40 * Math.PI / 180;// Math..ToRadians(35); //35 angle, can be adjusted
      double x = tipX - ArrowLen * Math.Cos(theta + ArrowAngle);
      double y = tipY - ArrowLen * Math.Sin(theta + ArrowAngle);

      //double phi2 = -40 * Math.PI / 180; //Math.toRadians(-35);//-35 angle, can be adjusted
      var phi2 = -ArrowAngle;
      double x2 = tipX - ArrowLen * Math.Cos(theta + phi2);
      double y2 = tipY - ArrowLen * Math.Sin(theta + phi2);
      var points = new[] { new PointF(tipX, tipY), new PointF((float)x, (float)y), new PointF((float)x2, (float)y2) };

      using (var arrowBrush = new SolidBrush(ArrowColor)) {
        if (ShadowLen > 0) {
          var shadowPoints = new PointF[points.Length];
          for (int i = 0; i < points.Length; i++) {
            shadowPoints[i].X = points[i].X + ShadowLen;
            shadowPoints[i].Y = points[i].Y + ShadowLen;
          }
          using (var shadowBrush = new SolidBrush(ShadowColor))
            g.FillPolygon(shadowBrush, shadowPoints, FillMode.Winding);
        }
        g.FillPolygon(arrowBrush, points, FillMode.Winding);

      }
    }


    public override void Normalize() {

    }


  }
}
